﻿#include "OperFESubSystem.h"
#include "GUIDialog/GUISubSystemDialog/GUIFESubSysFormSEASubSysDialog.h"
#include "GUIDialog/GUISubSystemDialog/GUIFESubSysStructDialog.h"
#include "GUIDialog/GUISubSystemDialog/SEASubSysGenerateMeshDialog.h"
#include "GUIDialog/GUISubSystemDialog/GUIFESubSysAcousticDialog.h"

#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysShellPlate.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysShellCurved.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysBeam.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEASubSysCavity.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEAFace.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscNodeList.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsTriangles.h"

#include "FITK_Component/FITKAcousticsModel/FITKAcousticsFEFace.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsFEModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractFESubSys.h"
#include "FITK_Component/FITKAcousticsModel/FITKFESubSysAcoustic.h"
#include "FITK_Component/FITKAcousticsModel/FITKFESubSysStructure.h"

#include "FITK_Component/FITKGmshMshIO/FITKGmshMshIOInterface.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMeshPartVTK.h"

#include "updateBrowserTable.h"
#include "GUIFrame/MainWindow.h"
#include "GUIFrame/CentralWidget.h"
#include "PickDataProvider/PickedDataProvider.h"
#include "PickDataProvider/PickedData.h"
#include "OperatorsInterface/GraphEventOperator.h"

#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKAppFramework/FITKMessage.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppSettings.h"

namespace ModelOper
{

    bool OperFESubSystem::execGUI()
    {
        if (!_emitter)return false;
        //获取动作名称
        QString actionName = _emitter->objectName();
        //创建动作
        if (actionName.contains("Create"))
            this->createOper();
        //修改问题
        else if (actionName.contains("Edit"))
            this->reviseOper();

        return false;
    }

    bool OperFESubSystem::execProfession()
    {
        //获取渲染器
        EventOper::GraphEventOperator* graphOper = FITKOPERREPO->getOperatorT<EventOper::GraphEventOperator>("GraphPreprocess");
        if (graphOper == nullptr)return false;
        //获取SEA子系统管理器
        Acoustics::FITKAcousticsDiscModel *discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel) return false;
        //获取板的数据
        Acoustics::FITKAcousticsSEAModel* seaModel = discModel->getSEAModel();
        if (!seaModel)return false;
        Acoustics::FITKAcousticsSEASubSysManager* subSysMgr = seaModel->getSEASubSysManager();
        if (!subSysMgr) return false;
        //渲染获取高亮FE子系统
        bool forceUpdate = false;
        QString operType;
        if (this->argValue<QString>("OperModelType", operType) && operType == "Create")
        {
            forceUpdate = true;
            int faceID = 0, objDataID = 0;
            bool isDeleteSEA = false;
            if (this->argValue("FaceDataObjID", faceID))
                graphOper->updateGraph(faceID, forceUpdate);
            this->argValue<int>("pickDataObjID", objDataID);
            if (this->argValue<bool>("IsDeleteSEA", isDeleteSEA) && isDeleteSEA == true)
            {
                Acoustics::FITKAbstractSEASubSysShell* shell = dynamic_cast<Acoustics::FITKAbstractSEASubSysShell*>(subSysMgr->getDataByID(objDataID));
                if (shell) delete shell;
                graphOper->updateSEASubSystems(true);
            }
        }

        //渲染层显示数据
        int objID = 0;

        if (this->argValue("objID", objID))
            graphOper->updateGraph(objID, forceUpdate);

        //更新表格
        ModelOper::updateBrowserTable();
        return true;
    }

    void OperFESubSystem::createOper()
    {
        GUI::MainWindow * mainWindow = dynamic_cast<GUI::MainWindow *>(FITKAPP->getGlobalData()->getMainWindow());
        if (!_emitter || !mainWindow) return;
        QString actionName = _emitter->objectName();
        //通过动作名称执行创建操作
        if (actionName == "actionCreateStructFESubsys")
            this->setArgs("FESubSysType", (int)Acoustics::FITKAbstractFESubSys::FESubSysType::FEStructure);
        else if (actionName == "actionCreateAcousticFESubsys")
            this->setArgs("FESubSysType", (int)Acoustics::FITKAbstractFESubSys::FESubSysType::FEAcoustic);
        else return;
        //拾取创建对象
        GUI::GUIFESubSysFormSEASubSysDialog* dialog = new GUI::GUIFESubSysFormSEASubSysDialog(this, mainWindow);
        dialog->init();
        connect(dialog, &QDialog::accepted, this, &OperFESubSystem::pickDataFinish);
        dialog->show();
    }

    void OperFESubSystem::reviseOper()
    {
        GUI::MainWindow * mainWindow = dynamic_cast<GUI::MainWindow *>(FITKAPP->getGlobalData()->getMainWindow());
        if (!mainWindow)return;
        int dataID = 0;
        if (!this->argValue("DataID", dataID))return;
        this->setArgs("OperModelType", "Edit");
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discModel)return;
        //获取FE数据
        Acoustics::FITKAcousticsFEModel* feModel = discModel->getFEModel();
        if (!feModel)return;
        Acoustics::FITKAcousticsFESubSysManager* subSysMgr = feModel->getFESubSysManager();
        if (!subSysMgr) return;
        Acoustics::FITKAbstractFESubSys* dataFEData = subSysMgr->getDataByID(dataID);
        if (!dataFEData)return;
        // 获取类型
        Acoustics::FITKAbstractFESubSys::FESubSysType type = dataFEData->getFESubSysType();
        //创建修改平板的窗口对象
        QDialog* dialog = nullptr;
        if (type == Acoustics::FITKAbstractFESubSys::FESubSysType::FEStructure)
        {
            this->setArgs("FESubSysType", (int)Acoustics::FITKAbstractFESubSys::FESubSysType::FEStructure);
            Acoustics::FITKFESubSysStructure* feStructure = dynamic_cast<Acoustics::FITKFESubSysStructure*>(dataFEData);
            if (!feStructure)return;
            dialog = new GUI::GUIFESubSysStructDialog(feStructure, this, mainWindow);
        }
        //创建修改单曲率板的窗口对象
        else if (type == Acoustics::FITKAbstractFESubSys::FESubSysType::FEAcoustic)
        {
            this->setArgs("FESubSysType", (int)Acoustics::FITKAbstractFESubSys::FESubSysType::FEAcoustic);
            Acoustics::FITKFESubSysAcoustic* feAcoustic = dynamic_cast<Acoustics::FITKFESubSysAcoustic*>(dataFEData);
            if (!feAcoustic)return;
            dialog = new GUI::GUIFESubSysAcousticDialog(feAcoustic, this, mainWindow);
        }
        if (!dialog)return;
        connect(dialog, &QDialog::accepted, this, &OperFESubSystem::execProfession);
        dialog->show();
    }

    bool OperFESubSystem::structureFESubSysPickData(Acoustics::FITKAbstractFESubSys* obj)
    {
        Acoustics::FITKFESubSysStructure* structureData = dynamic_cast<Acoustics::FITKFESubSysStructure*>(obj);
        if (!structureData)return false;
        GUI::MainWindow * mainWindow = dynamic_cast<GUI::MainWindow *>(FITKAPP->getGlobalData()->getMainWindow());
        if (!mainWindow) return false;
        int pickType = 0;
        if (!this->argValue<int>("PickType", pickType)) return false;
        //获取三维可视化对象管理
        GraphData::PickedDataProvider* pickProvider = GraphData::PickedDataProvider::getInstance();
        if (!pickProvider)return false;
        //获取拾取数据对象
        QList<GraphData::PickedData*> pickList = pickProvider->getPickedList();
        if (pickType == GUI::GUIPickInfo::PickObjType::POBJSEAShell || pickType == GUI::GUIPickInfo::PickObjType::POBJSEABeam)
        {
            int dim = 0;
            if (pickType == GUI::GUIPickInfo::PickObjType::POBJSEAShell)
                dim = 2;
            else if (pickType == GUI::GUIPickInfo::PickObjType::POBJSEABeam)
                dim = 1;
            //设置板
            int pickDataObjID = -1;
            for (GraphData::PickedData* pickData : pickList)
            {
                if (!pickData) continue;
                pickDataObjID = pickData->getPickedDataObjId();
            }
            if (pickDataObjID == -1) return false;
            this->setArgs("pickDataObjID", pickDataObjID);
            bool isCoalesceNode = false;
            double mergeNode = 0.0;
            if (!this->argValue<bool>("IsCoalesceNode", isCoalesceNode) || !this->argValue<double>("MergeNode", mergeNode))return false;
            //获取节点管理器 
            Acoustics::FITKAcousticsDiscModel *discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
            if (!discModel) return false;
            //获取板的数据
            Acoustics::FITKAcousticsSEAModel* seaModel = discModel->getSEAModel();
            if (!seaModel)return false;
            Acoustics::FITKAcousticsSEASubSysManager* subSysMgr = seaModel->getSEASubSysManager();
            if (!subSysMgr) return false;
            Acoustics::FITKAbstractSEASubSys* seaSubSys = subSysMgr->getDataByID(pickDataObjID);
            if (!seaSubSys) return false;
            Interface::FITKUnstructuredMesh meshObj;
            //生成脚本并进行网格划分
            GUI::SEASubSysGenerateMeshDialog dialog(this, mainWindow);
            dialog.setMeshData(&meshObj);
            if (dialog.startMeshGen())
                dialog.exec();
            if (!structureData->updateMesh(&meshObj, dim, isCoalesceNode, mergeNode)) return false;
            structureData->setAllElementPropID(seaSubSys->getPropSectionID());
        }
        else if (pickType == GUI::GUIPickInfo::PickObjType::POBJMeshCell2D || pickType == GUI::GUIPickInfo::PickObjType::POBJMeshCell1D)
        {
            //设置网格单元数据
            QHash<int, QList<int>> meshs;
            QHash <int, int> elemSectionMap;
            for (GraphData::PickedData* pickData : pickList)
            {
                if (!pickData) continue;
                QHash <int, int> elemSection;
                GraphData::PickedDataType pickType = pickData->getPickedDataType();
                if (GraphData::PickedDataType::MeshCellPick == pickType)
                {
                    //获取partID和单元Id
                    int partID = pickData->getPickedDataObjId();
                    QList<int> faceElemsID = pickData->getPickedIds();
                    if (faceElemsID.isEmpty()) continue;
                    elemSection = pickData->getPickedOtherIDs();
                    meshs.insert(partID, faceElemsID);
                }
                for (QHash <int, int>::iterator iter = elemSection.begin(); iter != elemSection.end(); ++iter)
                    elemSectionMap.insert(iter.key(), iter.value());
            }
            if (meshs.isEmpty())
                return false;
            if (!structureData->updateMesh(meshs, elemSectionMap)) return false;
        }
        if (pickType == GUI::GUIPickInfo::PickObjType::POBJSEAShell || pickType == GUI::GUIPickInfo::PickObjType::POBJMeshCell2D)
        {
            //获取离散数据
            Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
            if (!discModel)return false;
            //FE模型
            Acoustics::FITKAcousticsFEModel* feModel = discModel->getFEModel();
            if (!feModel)return false;
            Acoustics::FITKAcousticsFEFaceManager* feFaceMgr = feModel->getFEFaceManager();
            if (!feFaceMgr) return false;
            //生成Fe面
            QString name = "Structure FE Face-1";
            name = feFaceMgr->checkName(name);
            Acoustics::FITKAcousticsFEFace* feFace = structureData->generateFEFace();
            if (!feFace) return false;
            feFace->setDataObjectName(name);
            feFaceMgr->appendDataObj(feFace);
            this->setArgs("FaceDataObjID", feFace->getDataObjectID());
        }
        if (!structureData->updateGeoProp()) return false;
        return true;
    }

    bool OperFESubSystem::acousticsFESubSysPickData(Acoustics::FITKAbstractFESubSys* obj)
    {
        Acoustics::FITKFESubSysAcoustic* acousticData = dynamic_cast<Acoustics::FITKFESubSysAcoustic*>(obj);
        if (!acousticData)return false;
        GUI::MainWindow * mainWindow = dynamic_cast<GUI::MainWindow *>(FITKAPP->getGlobalData()->getMainWindow());
        if (!mainWindow) return false;
        int pickType = 0;
        if (!this->argValue<int>("PickType", pickType)) return false;
        //获取三维可视化对象管理
        GraphData::PickedDataProvider* pickProvider = GraphData::PickedDataProvider::getInstance();
        if (!pickProvider)return false;
        //获取拾取数据对象
        QList<GraphData::PickedData*> pickList = pickProvider->getPickedList();
        if (pickType == GUI::GUIPickInfo::PickObjType::POBJSEACavity)
        {
            //设置板
            int pickDataObjID = -1;
            for (GraphData::PickedData* pickData : pickList)
            {
                if (!pickData) continue;
                pickDataObjID = pickData->getPickedDataObjId();
            }
            if (pickDataObjID == -1) return false;
            this->setArgs("pickDataObjID", pickDataObjID);
            return false;
        }
        else if (pickType == GUI::GUIPickInfo::PickObjType::POBJMeshCell3D)
        {
            //设置网格单元数据
            QHash<int, QList<int>> meshs;
            QHash <int, int> elemSectionMap;
            for (GraphData::PickedData* pickData : pickList)
            {
                if (!pickData) continue;
                QHash <int, int> elemSection;
                GraphData::PickedDataType pickType = pickData->getPickedDataType();
                if (GraphData::PickedDataType::MeshCellPick == pickType)
                {
                    //获取partID和单元Id
                    int partID = pickData->getPickedDataObjId();
                    QList<int> faceElemsID = pickData->getPickedIds();
                    if (faceElemsID.isEmpty()) continue;
                    elemSection = pickData->getPickedOtherIDs();
                    meshs.insert(partID, faceElemsID);
                }
                for (QHash <int, int>::iterator iter = elemSection.begin(); iter != elemSection.end(); ++iter)
                    elemSectionMap.insert(iter.key(), iter.value());
            }
            if (meshs.isEmpty())
                return false;
            if (!acousticData->updateMesh(meshs, elemSectionMap)) return false;
        }
        if (!acousticData->updateGeoProp()) return false;
        return true;
    }


    void OperFESubSystem::pickDataFinish()
    {
        //获取主窗口
        GUI::MainWindow * mainWindow = dynamic_cast<GUI::MainWindow *>(FITKAPP->getGlobalData()->getMainWindow());
        if (!mainWindow)return;
        //创建板的类型
        int type = 0;
        if (!argValue<int>("FESubSysType", type))return;
        this->setArgs("OperModelType", "Create");

        //获取板类型
        Acoustics::FITKAbstractFESubSys::FESubSysType feSysType = Acoustics::FITKAbstractFESubSys::FESubSysType(type);
        //根据类型打开对应的创建板窗口
        QDialog* dialog = nullptr;
        if (type == Acoustics::FITKAbstractFESubSys::FESubSysType::FEStructure)
        {
            Acoustics::FITKFESubSysStructure* feStructure = new Acoustics::FITKFESubSysStructure;
            if (!this->structureFESubSysPickData(feStructure))
            {
                delete feStructure;
                feStructure = nullptr;
            }
            if (feStructure)
                dialog = new GUI::GUIFESubSysStructDialog(feStructure, this, mainWindow);
        }
        else if (type == Acoustics::FITKAbstractFESubSys::FESubSysType::FEAcoustic)
        {
            Acoustics::FITKFESubSysAcoustic* feAcoustic = new Acoustics::FITKFESubSysAcoustic;
            if (!this->acousticsFESubSysPickData(feAcoustic))
            {
                delete feAcoustic;
                feAcoustic = nullptr;
            }
            if (feAcoustic)
                dialog = new GUI::GUIFESubSysAcousticDialog(feAcoustic, this, mainWindow);
        }
        if (!dialog)
        {
            GUI::GUIPickInfo::ClearPickInfo();
            AppFrame::FITKMessageError("SEA Sub-System Create Err !!! pick data Err !");
            return;
        }
        connect(dialog, &QDialog::accepted, this, &OperFESubSystem::execProfession);
        dialog->show();
    }

}

